﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Threading.Tasks;
using Dapper;
using BCCommon.Extensions;
using BCEntity.Common.Area;
using System.Linq;
using BCCommon;

namespace BCData.Common.Area
{
    public class CountyData : ICountyData
    {
        private const string QUERY_SQL = @"SELECT c.CountyId,c.CountyCode,c.CityId,c.CityCode,c.CountyName,c.CountyHeatLevel,
                                            c.IsDowntown,cm.CityName,c.ArriveCityDistance,cm.CapitalCity,c.ProvinceId,
                                            p.ProvinceCode,p.ProvinceName,c.CountyEasyBackGoods,c.CreateTime,
                                            c.UpdateTime,c.Editer,cm.HeatLevel,cm.Municipality,cm.CityEasyBackGoods,
                                            p.ProvinceHeatLevel,p.ProvinceEasyBackGoods,c.CountyNegotiatedPrice,c.Longitude,c.Latitude 
                                        FROM County c 
                                        LEFT JOIN City cm ON c.CityCode=cm.CityCode 
                                        LEFT JOIN Province p ON cm.ProvinceCode=p.ProvinceCode";
        private const string INSERT_SQL = @"INSERT INTO County(CountyCode,CountyName,CityId,CityCode,CityName,ProvinceId,ProvinceCode,ProvinceName,IsDowntown,CountyHeatLevel,ArriveCityDistance,CountyEasyBackGoods,Editer,IsEnabled) 
                                            VALUES(?CountyCode,?CountyName,?CityId,?CityCode,?CityName,?ProvinceId,?ProvinceCode,?ProvinceName,?IsDowntown,?CountyHeatLevel,?ArriveCityDistance,?CountyEasyBackGoods,?Editer,?IsEnabled);";
        private const string UPDATE_SQL = @"UPDATE County SET 
                                                ProvinceId=?ProvinceId,
                                                ProvinceName=?ProvinceName,
                                                ProvinceCode=?ProvinceCode,
                                                CityId=?CityId,
                                                CityCode=?CityCode,
                                                CityName=?CityName,
                                                CountyCode=?CountyCode,
                                                CountyName=?CountyName,
                                                IsDowntown=?IsDowntown,
                                                CountyHeatLevel=?CountyHeatLevel,
                                                ArriveCityDistance=?ArriveCityDistance,
                                                CountyEasyBackGoods=?CountyEasyBackGoods,
                                                Editer=?Editer
                                            WHERE CountyId=?CountyId ";
        private const string DELETE_SQL = @"DELETE FROM County WHERE CountyCode=?CountyCode ";

        private static DateTime? LastLoadOrCheckTime = null;

        private static IEnumerable<CountyEntity> CachedRawData;
        private static IDictionary<string, CountyEntity> CachedByCountyId;

        protected readonly IDatabaseContext databaseContext;

        public CountyData(IDatabaseContext databaseContext)
        {
            this.databaseContext = databaseContext;
        }

        private void EnsureCache()
        {
            bool reload = false;

            if (LastLoadOrCheckTime == null)
            {
                reload = true;
            }

            if (LastLoadOrCheckTime < DateTime.Now.AddSeconds(-293))
            {
                // 可能也要考虑 Province.UpdateTime 和 City.UpdateTime 的。
                var lastUpdateTime = this.databaseContext.Slave.ExecuteScalar<DateTime>("SELECT UpdateTime FROM county ORDER BY UpdateTime DESC LIMIT 1");

                if (lastUpdateTime > LastLoadOrCheckTime)
                {
                    reload = true;
                }
                else
                {
                    LastLoadOrCheckTime = DateTime.Now;
                }
            }

            if (reload)
            {
                LastLoadOrCheckTime = DateTime.Now;

                CachedRawData = this.databaseContext.Slave.Query<CountyEntity>(QUERY_SQL);

                CachedByCountyId = new Dictionary<string, CountyEntity>();

                foreach (var item in CachedRawData)
                {
                    CachedByCountyId.TryAdd(item.CountyCode, item);
                }
            }
        }

        public bool Add(CountyEntity entity)
        {
            LastLoadOrCheckTime = null;

            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?CityId", entity.CityId, DbType.Int64, size: 20);
            parameters.Add("?CityCode", entity.CityCode, DbType.AnsiString, size: 20);
            parameters.Add("?CityName", entity.CityName, DbType.AnsiString, size: 30);

            parameters.Add("?ProvinceId", entity.ProvinceId, DbType.Int64, size: 20);
            parameters.Add("?ProvinceCode", entity.ProvinceCode, DbType.AnsiString, size: 20);
            parameters.Add("?ProvinceName", entity.ProvinceName, DbType.AnsiString, size: 50);

            parameters.Add("?CountyCode", entity.CountyCode, DbType.AnsiString, size: 20);
            parameters.Add("?CountyName", entity.CountyName, DbType.AnsiString, size: 100);

            parameters.Add("?CountyHeatLevel", entity.CountyHeatLevel, DbType.Int32, size: 11);
            parameters.Add("?IsDowntown", entity.IsDowntown, DbType.Boolean);
            parameters.Add("?ArriveCityDistance", entity.ArriveCityDistance, DbType.Int32, size: 11);
            parameters.Add("?CountyEasyBackGoods", entity.CountyEasyBackGoods.ToString(), DbType.AnsiString);
            parameters.Add("?Editer", entity.Editer, DbType.AnsiString, size: 20);
            parameters.Add("?IsEnabled", entity.IsEnabled, DbType.Boolean);
            
            int result = this.databaseContext.Master.Execute(INSERT_SQL, parameters, databaseContext.Transaction);
            return result > 0;
        }

        public bool Update(CountyEntity entity)
        {
            LastLoadOrCheckTime = null;

            DynamicParameters parameters = new DynamicParameters();

            parameters.Add("?CityId", entity.CityId, DbType.Int64, size: 20);
            parameters.Add("?CityCode", entity.CityCode, DbType.AnsiString, size: 20);
            parameters.Add("?CityName", entity.CityName, DbType.AnsiString, size: 30);

            parameters.Add("?ProvinceId", entity.ProvinceId, DbType.Int64, size: 20);
            parameters.Add("?ProvinceCode", entity.ProvinceCode, DbType.AnsiString, size: 20);
            parameters.Add("?ProvinceName", entity.ProvinceName, DbType.AnsiString, size: 50);

            parameters.Add("?CountyCode", entity.CountyCode, DbType.AnsiString, size: 20);
            parameters.Add("?CountyName", entity.CountyName, DbType.AnsiString, size: 100);

            parameters.Add("?CountyHeatLevel", entity.CountyHeatLevel, DbType.Int32, size: 11);
            parameters.Add("?IsDowntown", entity.IsDowntown, DbType.Boolean);
            parameters.Add("?ArriveCityDistance", entity.ArriveCityDistance, DbType.Int32, size: 11);
            parameters.Add("?CountyEasyBackGoods", entity.CountyEasyBackGoods.ToString(), DbType.AnsiString);
            parameters.Add("?Editer", entity.Editer, DbType.AnsiString, size: 20);

            return this.databaseContext.Master.Execute(UPDATE_SQL, parameters, databaseContext.Transaction) != 0;
        }

        public bool Delete(string countyCode)
        {
            LastLoadOrCheckTime = null;

            DynamicParameters parameter = new DynamicParameters();

            parameter.Add("?CountyCode", countyCode, DbType.AnsiString, size: 20);
            return this.databaseContext.Master.Execute(DELETE_SQL, parameter, databaseContext.Transaction) > 0;
        }
        public bool CheckExistsById(long countyId)
        {
            string sql = @"SELECT 1 FROM County WHERE CountyId=?CountyId LIMIT 1";
            DynamicParameters parameter = new DynamicParameters();
            parameter.Add("?CountyId", countyId, DbType.Int64);
            object result = this.databaseContext.Slave.ExecuteScalar(sql, parameter);
            return result != null;
        }
        public bool CheckExistsByCode(string countyCode)
        {
            string sql = @"SELECT 1 FROM County WHERE CountyCode=?CountyCode LIMIT 1";
            DynamicParameters parameter = new DynamicParameters();
            parameter.Add("?CountyCode", countyCode, DbType.AnsiString, size: 20);
            object result = this.databaseContext.Slave.ExecuteScalar(sql, parameter);
            return result != null;
        }

        public bool CheckCountyCodeExists(string countyCode, string cityCode)
        {
            string sql = @"SELECT 1 FROM County WHERE CountyCode=?CountyCode AND CityCode=?CityCode  LIMIT 1";

            DynamicParameters parameter = new DynamicParameters();
            parameter.Add("?CountyCode", countyCode, DbType.AnsiString, size: 20);
            parameter.Add("?CityCode", cityCode, DbType.AnsiString, size: 20);
            object result = this.databaseContext.Slave.ExecuteScalar(sql, parameter);
            return result != null;
        }

        public bool CheckCityCodeExists(string cityCode)
        {
            string sql = @"SELECT 1 FROM County WHERE CityCode =?CityCode LIMIT 1";

            DynamicParameters parameter = new DynamicParameters();

            parameter.Add("?CityCode", cityCode, DbType.AnsiString, size: 20);

            return this.databaseContext.Slave.ExecuteScalar(sql, parameter) != null;
        }

        public IEnumerable<CountyEntity> GetCounties(string cityCode)
        {
            this.EnsureCache();

            if (!string.IsNullOrWhiteSpace(cityCode))
            {
                return CachedRawData.Where(p => p.CityCode == cityCode);
            }

            return CachedRawData;
        }

        public IEnumerable<CountyEntity> GetCounties(long cityId)
        {
            this.EnsureCache();

            return CachedRawData.Where(p => p.CityId == cityId);
        }

        public CountyEntity GetCounty(long countyId)
        {
            
            string sql = string.Format(@"{0} WHERE c.CountyId=?CountyId", QUERY_SQL);

            DynamicParameters parameter = new DynamicParameters();
            parameter.Add("?CountyId", countyId, DbType.Int64, size: 20);

            return this.databaseContext.Slave.QueryEntity<CountyEntity>(sql, parameter);
        }

        public CountyEntity GetCounty(string countyCode)
        {
            this.EnsureCache();

            if (CachedByCountyId.TryGetValue(countyCode, out var value))
            {
                return value;
            }
            else
            {
                string sql = string.Format(@"{0} WHERE c.CountyCode=?CountyCode", QUERY_SQL);

                DynamicParameters parameter = new DynamicParameters();
                parameter.Add("?CountyCode", countyCode, DbType.AnsiString, size: 20);

                return this.databaseContext.Slave.QueryEntity<CountyEntity>(sql, parameter);
            }
        }

        public IEnumerable<CountyEntity> GetCounties(string provinceCode, string cityCode, string countyCode, int index, int size, out int dataCount)
        {
            List<string> wheres = new List<string>();
            DynamicParameters parameters = new DynamicParameters();

            if (!string.IsNullOrWhiteSpace(countyCode))
            {
                wheres.Add("c.CountyCode = ?CountyCode");
                parameters.Add("?CountyCode", countyCode, DbType.AnsiString, size: 20);
            }

            if (!string.IsNullOrWhiteSpace(cityCode))
            {
                wheres.Add("c.CityCode = ?CityCode");
                parameters.Add("?CityCode", cityCode, DbType.AnsiString, size: 20);
            }

            if (!string.IsNullOrWhiteSpace(provinceCode))
            {
                wheres.Add("cm.ProvinceCode = ?ProvinceCode");
                parameters.Add("?ProvinceCode", provinceCode, DbType.AnsiString, size: 20);
            }

            string sql = string.Format("{0} {1} LIMIT {2}, {3}; SELECT COUNT(1) FROM County c LEFT JOIN City cm ON c.CityCode = cm.CityCode {1}",
                QUERY_SQL,
                wheres.Count > 0 ? "WHERE " + string.Join(" AND ", wheres) : string.Empty,
                (index == 0 ? 0 : index - 1) * size,
                size);

            var results = this.databaseContext.Slave.QueryMultiple<CountyEntity, int>(sql, parameters);

            dataCount = results.Item2;

            return results.Item1;
        }

        public IEnumerable<CountyEntity> GetCounty(string provinceCode, string cityCode)
        {
            this.EnsureCache();

            return CachedRawData.Where(p => p.ProvinceCode == provinceCode && p.CityCode == cityCode);
        }

        public bool UpdateCountyNegotiatedPrice(string countyCode, bool isNegotiatedPrice)
        {
            LastLoadOrCheckTime = null;

            string sql = @"UPDATE County SET 
                                    CountyNegotiatedPrice=?CountyNegotiatedPrice
                                WHERE CountyCode=?CountyCode";
            DynamicParameters parameter = new DynamicParameters();
            parameter.Add("?CountyCode", countyCode, DbType.AnsiString, size: 20);
            parameter.Add("?CountyNegotiatedPrice", isNegotiatedPrice, DbType.Boolean);
            var result = this.databaseContext.Master.Execute(sql, parameter,databaseContext.Transaction);
            return result != 0;

        }

        public async Task<CountyEntity> GetCountyAsync(string countyUuid, string countyName, string countyCode, string cityCode)
        {
            List<string> wheres = new List<string>();
            string sql = @"SELECT A.CountyId,A.CountyCode,A.CityCode,A.CountyName,A.IsDowntown,
                        A.CountyHeatLevel,A.ArriveCityDistance,A.CountyEasyBackGoods,
                        A.CreateTime,A.UpdateTime,A.Editer,A.CountyNegotiatedPrice,A.Longitude,A.Latitude,A.CountyUuid,A.IsEnabled,
                        B.CityCode,B.CityName,C.ProvinceCode,C.ProvinceName,A.Longitude,A.Latitude 
                        FROM County A LEFT JOIN City B ON A.CityCode = B.CityCode 
                        LEFT JOIN Province C ON C.ProvinceCode = B.ProvinceCode";
            DynamicParameters parameter = new DynamicParameters();
            if (!string.IsNullOrWhiteSpace(countyCode))
            {
                if (countyCode.Length == 2)
                {
                    wheres.Add("RIGHT(A.CountyCode,2)=?CountyCode");
                }
                else
                {
                    wheres.Add("A.CountyCode=?CountyCode");
                }
                parameter.Add("?CountyCode", countyCode, DbType.AnsiString);
            }
            if (!string.IsNullOrWhiteSpace(countyName))
            {
                wheres.Add("A.CountyName LIKE ?CountyName");
                parameter.Add("?CountyName", countyName + "%", DbType.AnsiString);
            }
            if (!string.IsNullOrWhiteSpace(countyUuid))
            {
                wheres.Add("A.CountyUuid=?CountyUuid");
                parameter.Add("?CountyUuid", countyUuid, DbType.AnsiString);
            }
            if (!string.IsNullOrWhiteSpace(cityCode))
            {
                wheres.Add("A.CityCode=?CityCode");
                parameter.Add("?CityCode", cityCode, DbType.AnsiString);
            }
            sql = string.Format(@"{0} {1} LIMIT 1", sql, wheres.Count > 0 ? " WHERE " + string.Join(" AND ", wheres) : string.Empty);
            return await this.databaseContext.Slave.QueryFirstOrDefaultAsync<CountyEntity>(sql, parameter);
        }

        public async Task<int> AddCountyAsync(CountyEntity entity, string batchNo)
        {
            LastLoadOrCheckTime = null;
            string sql = @"INSERT INTO County(CountyCode,CityCode,CountyName,IsDowntown,CountyHeatLevel,ArriveCityDistance,CountyEasyBackGoods,
                        Editer,CountyNegotiatedPrice,Longitude,Latitude,CountyUuid,IsEnabled)
                        VALUES(?CountyCode,?CityCode,?CountyName,?IsDowntown,?CountyHeatLevel,?ArriveCityDistance,?CountyEasyBackGoods,
                        ?Editer,?CountyNegotiatedPrice,?Longitude,?Latitude,UUID(),?IsEnabled);";
            DynamicParameters parameter = new DynamicParameters();
            parameter.Add("?CityCode", entity.CityCode, DbType.AnsiString, size: 20);
            parameter.Add("?CountyName", entity.CountyName, DbType.AnsiString, size: 100);
            parameter.Add("?CountyHeatLevel", entity.CountyHeatLevel, DbType.Int32, size: 11);
            parameter.Add("?IsDowntown", entity.IsDowntown, DbType.Boolean);
            parameter.Add("?ArriveCityDistance", entity.ArriveCityDistance, DbType.Int32, size: 11);
            parameter.Add("?CountyEasyBackGoods", entity.CountyEasyBackGoods.ToString(), DbType.AnsiString);
            parameter.Add("?CountyNegotiatedPrice", entity.CountyNegotiatedPrice, DbType.Boolean);
            parameter.Add("?Editer", entity.Editer, DbType.AnsiString, size: 20);
            parameter.Add("?Longitude", entity.Longitude, DbType.Double);
            parameter.Add("?Latitude", entity.Latitude, DbType.Double);
            parameter.Add("?CountyCode", entity.CountyCode, DbType.AnsiString, size: 20);
            parameter.Add("?IsEnabled", entity.IsEnabled, DbType.Boolean);
            var result = await this.databaseContext.Master.ExecuteAsync(sql, parameter, databaseContext.Transaction) > 0;
            if (!result)
            {
                throw new ArgumentException("添加区县信息失败!");
            }
            sql = this.GetUpdateCityChange(entity, batchNo, out DynamicParameters updateParameter);
            return await this.databaseContext.Master.ExecuteAsync(sql, updateParameter,databaseContext.Transaction);
        }

        public async Task<int> UpdateCountyAsync(CountyEntity entity, string batchNo, CountyEntity countryResult, bool? isMatch)
        {
            LastLoadOrCheckTime = null;

            string sql = @"UPDATE County SET 
                                UpdateTime=NOW(),
                                Editer=?Editer,
                                Longitude=?Longitude,
                                Latitude=?Latitude,
                                IsEnabled=?IsEnabled
                            WHERE CountyUuid=?CountyUuid";
            DynamicParameters parameter = new DynamicParameters();
            parameter.Add("?Editer", entity.Editer, DbType.AnsiString, size: 20);
            parameter.Add("?Longitude", entity.Longitude, DbType.Double);
            parameter.Add("?Latitude", entity.Latitude, DbType.Double);
            parameter.Add("?IsEnabled", entity.IsEnabled.Value, DbType.Boolean);
            parameter.Add("?CountyUuid", entity.CountyUuid, DbType.AnsiString);
            var result = await this.databaseContext.Master.ExecuteAsync(sql, parameter, databaseContext.Transaction)>0;
            if (!result)
            {
                throw new ArgumentException("修改城市信息失败!");
            }
            if (isMatch.HasValue&& !isMatch.Value)
            {
                sql = this.GetUpdateCityChange(entity, batchNo, countryResult, out DynamicParameters updateParameter);
                return await this.databaseContext.Master.ExecuteAsync(sql, updateParameter, databaseContext.Transaction);
            }
            return result ? 1 : 0;
        }

        private string GetUpdateCityChange(CountyEntity entity, string batchNo, CountyEntity countryResult, out DynamicParameters updateParameter)
        {
            updateParameter = new DynamicParameters();
            string sql_cityChange = SqlCommands.GetInsertSql("CityChange",
                new string[] { "BatchNo", "OldProvinceCode", "NewProvinceCode", "OldProvinceName", "NewProvinceName",
                    "OldCityCode","NewCityCode","OldCityName","NewCityName",
                    "OldCountyCode","NewCountyCode","OldCountyName","NewCountyName",
                    "OldCountyLongitude","NewCountyLongitude","OldCountyLatitude","NewCountyLatitude","IsChange", "Type", "Content" });
            updateParameter.Add("IsChange", true, DbType.Boolean);
            updateParameter.Add("Content", "更新区县信息 " + countryResult.CountyCode + ":" + countryResult.CountyName + " 为 " + entity.CountyCode + ":" + entity.CountyName, DbType.AnsiString);
            updateParameter.Add("?BatchNo", batchNo, DbType.AnsiString);
            updateParameter.Add("?OldProvinceCode", countryResult.ProvinceCode, DbType.AnsiString);
            updateParameter.Add("?NewProvinceCode", entity.ProvinceCode, DbType.AnsiString);
            updateParameter.Add("?OldProvinceName", countryResult.ProvinceName, DbType.AnsiString);
            updateParameter.Add("?NewProvinceName", entity.ProvinceName, DbType.AnsiString);
            updateParameter.Add("?OldCityCode", countryResult.CityCode, DbType.AnsiString);
            updateParameter.Add("?NewCityCode", entity.CityCode, DbType.AnsiString);
            updateParameter.Add("?OldCityName", countryResult.CityName, DbType.AnsiString);
            updateParameter.Add("?NewCityName", entity.CityName, DbType.AnsiString);
            updateParameter.Add("?OldCountyCode", countryResult.CountyCode, DbType.AnsiString);
            updateParameter.Add("?NewCountyCode", entity.CountyCode, DbType.AnsiString);
            updateParameter.Add("?OldCountyName", countryResult.CountyName, DbType.AnsiString);
            updateParameter.Add("?NewCountyName", entity.CountyName, DbType.AnsiString);
            updateParameter.Add("?OldCountyLongitude", countryResult.Longitude, DbType.Double);
            updateParameter.Add("?NewCountyLongitude", entity.Longitude, DbType.Double);
            updateParameter.Add("?OldCountyLatitude", countryResult.Latitude, DbType.Double);
            updateParameter.Add("?NewCountyLatitude", entity.Latitude, DbType.Double);
            updateParameter.Add("?Type", "County", DbType.AnsiString);
            return sql_cityChange;
        }

        private string GetUpdateCityChange(CountyEntity entity, string batchNo, out DynamicParameters updateParameter)
        {
            updateParameter = new DynamicParameters();
            string sql_cityChange = SqlCommands.GetInsertSql("CityChange",
                new string[] { "BatchNo", "NewProvinceCode", "NewProvinceName", "NewCityCode", "NewCityName", "NewCountyCode", "NewCountyName",
                    "NewCountyLongitude", "NewCountyLatitude", "IsNew", "Type", "Content" });
            updateParameter.Add("IsNew", true, DbType.Boolean);
            updateParameter.Add("Content", "写入新区县信息 " + entity.CountyCode + ":" + entity.CountyName, DbType.AnsiString);
            updateParameter.Add("?BatchNo", batchNo, DbType.AnsiString);
            updateParameter.Add("?NewProvinceCode", entity.ProvinceCode, DbType.AnsiString);
            updateParameter.Add("?NewProvinceName", entity.ProvinceName, DbType.AnsiString);
            updateParameter.Add("?NewCityCode", entity.CityCode, DbType.AnsiString);
            updateParameter.Add("?NewCityName", entity.CityName, DbType.AnsiString);
            updateParameter.Add("?NewCountyCode", entity.CountyCode, DbType.AnsiString);
            updateParameter.Add("?NewCountyName", entity.CountyName, DbType.AnsiString);
            updateParameter.Add("?NewCountyLongitude", entity.Longitude.Value, DbType.Double);
            updateParameter.Add("?NewCountyLatitude", entity.Latitude, DbType.Double);
            updateParameter.Add("?Type", "County", DbType.AnsiString);
            return sql_cityChange;
        }

        public async Task<bool> UpdateIsEnabledAsync(string batchNo)
        {
            string insertSql = @"INSERT INTO CityChange(BatchNo,OldProvinceCode,OldProvinceName,OldProvinceLongitude,OldProvinceLatitude,
                                OldCityCode,OldCityName,OldCityLongitude,OldCityLatitude,
                                OldCountyCode,OldCountyName,OldCountyLongitude,OldCountyLatitude,IsDel,Type,Content) 
                                SELECT ?BatchNo,C.ProvinceCode,C.ProvinceName,C.Longitude,C.Latitude,B.CityCode,B.CityName,B.Longitude,B.Latitude,
                                A.CountyCode,A.CountyName,A.Longitude,A.Latitude,?IsDel,?Type,?Content FROM County A 
                                LEFT JOIN City B ON A.CityCode = B.CityCode 
                                LEFT JOIN Province C ON C.ProvinceCode = B.ProvinceCode 
                                WHERE A.IsEnabled = 0";
            DynamicParameters cityChangeParameters = new DynamicParameters();
            cityChangeParameters.Add("?BatchNo", batchNo, DbType.AnsiString);
            cityChangeParameters.Add("?IsDel", true, DbType.Boolean);
            cityChangeParameters.Add("?Type", "County", DbType.AnsiString);
            cityChangeParameters.Add("?Content", "写入未匹配上区县信息", DbType.AnsiString);
            return await this.databaseContext.Master.ExecuteAsync(insertSql, cityChangeParameters,databaseContext.Transaction) != 0;
        }

        public async Task<IEnumerable<CountyEntity>> GetList()
        {
            return await databaseContext.Slave.QueryAsync<CountyEntity>(QUERY_SQL);
        }
    }
}
